# kopano-dagent RewriteGALAddressesToSMTP
# (c) 2017 Hein-Pieter van Braam <hp@tmm.cx>
# (C) 2020 Christoph Haas <christoph.h@sprinternet.at>
# Licensed under the GPU Affero GPL v3 (or at your option any later version)
# See LICENSE file for details

import MAPI
import email
from email.utils import getaddresses
from email.header import decode_header

from MAPI.Util import *
from plugintemplates import *

class RewriteGALAddressesToSMTP(IMapiDAgentPlugin):
    
    def __init__(self, logger):
        IMapiDAgentPlugin.__init__(self, logger)

    def DecodeHeaderToUTF8(self, header) -> str:
        decodedHeaderParts = decode_header(header)

        strHeader = ""
        for headerText, headerEncoding in decodedHeaderParts:
            if headerEncoding is None:
                if isinstance(headerText, str):
                    strHeader += headerText  # already a string
                else:
                    strHeader += headerText.decode('ASCII')
            else:
                strHeader += headerText.decode(headerEncoding)
        return strHeader

    def GetKopanoRecipient(self, emailAddr: bytes, kopanoRecipients: list) -> list:
        for rcpt in kopanoRecipients:
            if SPropValue(PR_EMAIL_ADDRESS, emailAddr) in rcpt:
                return rcpt
        return None

    # PreDelivery hook entry point
    def PreDelivery(self, session, addrbook, store, folder, message):
        # Load headers and extract To: and CC: headers
        headers = message.GetProps([PR_TRANSPORT_MESSAGE_HEADERS], 0)[0].Value
        msg = email.message_from_bytes(headers)
        to_addrs = getaddresses(msg.get_all('to', []))
        cc_addrs = getaddresses(msg.get_all('cc', []))

        # First load all original recipients for the message
        orig_to_addrs = []
        orig_cc_addrs = []
        rcptTable = message.GetRecipientTable(0)
        #rcptTable.SetColumns([PR_EMAIL_ADDRESS, PR_ADDRTYPE], 0)  # no specific columns means: load all columns
        origRcpts = rcptTable.QueryRows(10, 0)
        while origRcpts and len(origRcpts) > 0:
            for origRcpt in origRcpts:
                if SPropValue(PR_RECIPIENT_TYPE, MAPI_TO) in origRcpt:
                    orig_to_addrs.append(origRcpt)
                if SPropValue(PR_RECIPIENT_TYPE, MAPI_CC) in origRcpt:
                    orig_cc_addrs.append(origRcpt)
            origRcpts = rcptTable.QueryRows(10, 0)  # Read the next 10 recipients


        # Now replace alias addresses with the SMTP address type
        names = []
        for addr in to_addrs:
            kopanoRcpt = self.GetKopanoRecipient(bytes(addr[1], encoding='utf8'), orig_to_addrs)
            if kopanoRcpt is not None:
                names.append(kopanoRcpt)  # keep original To: entry
            else:
                names.append([
                    SPropValue(PR_RECIPIENT_TYPE, MAPI_TO),
                    SPropValue(PR_DISPLAY_NAME, bytes(self.DecodeHeaderToUTF8(addr[0]), encoding="utf8")),
                    SPropValue(PR_ADDRTYPE, bytes('SMTP', encoding="utf8")),
                    SPropValue(PR_EMAIL_ADDRESS, bytes(addr[1], encoding='utf8')),
                ])

        for addr in cc_addrs:
            kopanoRcpt = self.GetKopanoRecipient(bytes(addr[1], encoding='utf8'), orig_cc_addrs)
            if kopanoRcpt is not None:
                names.append(kopanoRcpt)  # keep original CC: entry
            else:
                names.append([
                    SPropValue(PR_RECIPIENT_TYPE, MAPI_CC),
                    SPropValue(PR_DISPLAY_NAME, bytes(self.DecodeHeaderToUTF8(addr[0]), encoding="utf8")),
                    SPropValue(PR_ADDRTYPE, bytes('SMTP', encoding="utf8")),
                    SPropValue(PR_EMAIL_ADDRESS, bytes(addr[1], encoding='utf8')),
                ])

        if len(names) > 0:  # double check, avoid empty recipients
            message.ModifyRecipients(0, names)
        return MP_CONTINUE,